//
// Created by kuang on 2025/9/18.
//

#ifndef IENA_LIB_H
#define IENA_LIB_H
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>

/* IENA包类型定义 */
typedef enum {
    IENA_TYPE_P = 0x80,  /* P型包 - 位置参数 (Bit7=1) */
    IENA_TYPE_M = 0x30,  /* M型包 - 带延迟的信息参数 (Bit5=1, Bit4=1) */
    IENA_TYPE_Q = 0x20,  /* Q型包 - 不带延迟的信息参数 (Bit5=1, Bit4=0) */
    IENA_TYPE_D = 0x10,  /* D型包 - 带延迟的标准参数 (Bit5=0, Bit4=1) */
    IENA_TYPE_N = 0x00   /* N型包 - 不带延迟的标准参数 (Bit5=0, Bit4=0) */
} iena_packet_type_t;

/* 参数数据长度枚举 (以16位字为单位) */
typedef enum {
    IENA_WORDLEN_1 = 1,  /* 1个字 = 2字节 */
    IENA_WORDLEN_2 = 2,  /* 2个字 = 4字节 */
    IENA_WORDLEN_3 = 3,  /* 3个字 = 6字节 */
    IENA_WORDLEN_4 = 4,  /* 4个字 = 8字节 */
    IENA_WORDLEN_5 = 5,  /* 5个字 = 10字节 */
    IENA_WORDLEN_6 = 6,  /* 6个字 = 12字节 */
    IENA_WORDLEN_7 = 7   /* 7个字 = 14字节 */
} iena_word_length_t;

/* IENA状态位定义 */
#define IENA_STATUS_LATENCY_ERROR   (1 << 0)
#define IENA_STATUS_OVERFLOW_ERROR  (1 << 1)
#define IENA_STATUS_GPS_UNLOCK      (1 << 3)
#define IENA_STATUS_LOCAL_UNLOCK    (1 << 4)

/* IENA包尾标识 */
#define IENA_END_FIELD 0xDEAD

/* 最大包大小限制 */
#define IENA_MAX_PACKET_SIZE 65506
#define IENA_MIN_PACKET_SIZE 16
#define IENA_HEADER_SIZE 14
#define IENA_TRAILER_SIZE 2

/* IENA通用包头结构 (紧凑对齐) */
typedef struct __attribute__((packed)) {
    uint16_t iena_key;     /* IENA Key - 包标识符 */
    uint16_t size;         /* Size - 整个包的长度 */
    uint8_t  time[6];      /* Time - 48位时间戳 */
    uint8_t  key_status;   /* Key Status - 包类型和配置 */
    uint8_t  status;       /* Status - 运行时状态 */
    uint16_t seq_num;      /* SEQ NUM - 序列号 */
} iena_header_t;

/* IENA键配置结构 */
typedef struct {
    uint16_t key_id;                    /* 键ID */
    iena_packet_type_t packet_type;     /* 包类型 */
    iena_word_length_t word_length;     /* 参数字长度 (仅P/D/N型) */
    uint16_t max_data_size;            /* 数据体最大长度 */
    uint8_t param_count;               /* 参数个数 (仅P型) */
    uint16_t seq_num;                  /* 当前序列号 */
} iena_key_config_t;

/* IENA包构建器结构 */
typedef struct {
    uint8_t *buffer;                    /* 包缓冲区指针 */
    uint16_t buffer_size;              /* 缓冲区总大小 */
    uint16_t current_pos;              /* 当前写入位置 */
    iena_key_config_t *key_config;     /* 键配置指针 */
    uint8_t is_header_written;         /* 包头是否已写入 */
} iena_builder_t;

/* 时间戳获取函数指针类型 */
typedef uint64_t (*iena_timestamp_func_t)(void);

/* 状态获取函数指针类型 */
typedef uint8_t (*iena_status_func_t)(void);

/* ==================== 核心API函数 ==================== */

/**
 * 初始化IENA包构建器
 * @param builder: 构建器结构指针
 * @param buffer: 包缓冲区
 * @param buffer_size: 缓冲区大小
 * @param key_config: 键配置
 * @return: 0成功, 非0失败
 */
int iena_builder_init(iena_builder_t *builder,
                      uint8_t *buffer,
                      uint16_t buffer_size,
                      iena_key_config_t *key_config);

/**
 * 开始构建IENA包 (写入包头)
 * @param builder: 构建器指针
 * @param get_timestamp: 时间戳获取函数
 * @param get_status: 状态获取函数
 * @return: 0成功, 非0失败
 */
int iena_begin_packet(iena_builder_t *builder,
                      iena_timestamp_func_t get_timestamp,
                      iena_status_func_t get_status);

/**
 * P型包 - 添加一组参数数据
 * @param builder: 构建器指针
 * @param param_data: 参数数据数组
 * @param param_count: 参数个数
 * @return: 0成功, 非0失败
 */
int iena_add_p_params(iena_builder_t *builder,
                      const void *param_data,
                      uint8_t param_count);

/**
 * M型包 - 添加一个参数块
 * @param builder: 构建器指针
 * @param param_id: 参数ID
 * @param offset: 时间偏移
 * @param data: 数据指针
 * @param data_len: 数据长度
 * @return: 0成功, 非0失败
 */
int iena_add_m_param(iena_builder_t *builder,
                     uint16_t param_id,
                     uint16_t offset,
                     const void *data,
                     uint16_t data_len);

/**
 * Q型包 - 添加一个参数块
 * @param builder: 构建器指针
 * @param param_id: 参数ID
 * @param data: 数据指针
 * @param data_len: 数据长度
 * @return: 0成功, 非0失败
 */
int iena_add_q_param(iena_builder_t *builder,
                     uint16_t param_id,
                     const void *data,
                     uint16_t data_len);

/**
 * D型包 - 添加一个参数块
 * @param builder: 构建器指针
 * @param param_id: 参数ID
 * @param delay: 延迟值
 * @param data: 数据指针
 * @return: 0成功, 非0失败
 */
int iena_add_d_param(iena_builder_t *builder,
                     uint16_t param_id,
                     uint16_t delay,
                     const void *data);

/**
 * N型包 - 添加一个参数块
 * @param builder: 构建器指针
 * @param param_id: 参数ID
 * @param data: 数据指针
 * @return: 0成功, 非0失败
 */
int iena_add_n_param(iena_builder_t *builder,
                     uint16_t param_id,
                     const void *data);

/**
 * 完成IENA包构建 (写入包尾并更新包头大小)
 * @param builder: 构建器指针
 * @return: 最终包的总长度, 0表示失败
 */
uint16_t iena_finalize_packet(iena_builder_t *builder);

/**
 * 重置构建器以构建下一个包
 * @param builder: 构建器指针
 */
void iena_reset_builder(iena_builder_t *builder);

/* ==================== 辅助函数 ==================== */

/**
 * 创建键状态字节
 * @param packet_type: 包类型
 * @param word_length: 字长度 (仅P/D/N型有效)
 * @return: 键状态字节
 */
uint8_t iena_make_key_status(iena_packet_type_t packet_type,
                             iena_word_length_t word_length);

/**
 * 48位时间戳转换为字节数组
 * @param timestamp: 64位时间戳
 * @param time_bytes: 6字节输出数组
 */
void iena_timestamp_to_bytes(uint64_t timestamp, uint8_t time_bytes[6]);

/**
 * 字节数组转换为48位时间戳
 * @param time_bytes: 6字节时间数组
 * @return: 64位时间戳
 */
uint64_t iena_bytes_to_timestamp(const uint8_t time_bytes[6]);

/**
 * 以表格形式打印IENA包头结构
 * @param packet_data: IENA包数据指针
 */
void iena_print_header_table(const uint8_t *packet_data);

/**
 * 以表格形式打印IENA包的完整结构
 * @param packet_data: IENA包数据指针
 * @param packet_size: 包的总大小
 */
void iena_print_packet_table(const uint8_t *packet_data, uint16_t packet_size);

#endif /* IENA_LIB_H */